#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <time.h>

#define LEN 81
#define MAXBKS 100
#define TYPELEN 3
#define SWAP(type, a, b)    do {type c=a; a=b; b=c;} while(0)

typedef struct {
    char title[LEN];
    char author[LEN];
    float value;
} Book;

typedef int (* SORT_CB_PT)(const Book *, const Book *);

char * to_lower(char *);
char * s_gets(char *, int);

void bsort(Book **, int, SORT_CB_PT);
int comp_by_title(const Book *, const Book *);
int comp_by_value(const Book *, const Book *);
int comp_by_author(const Book *, const Book *);

int main(void)
{
    Book library[MAXBKS];
    Book * bkpt[MAXBKS];

    int ct = 0;
    int index;
    int type;

    SORT_CB_PT scbs[TYPELEN] = {comp_by_title, comp_by_author, comp_by_value};
    char * stis[TYPELEN] = {"sort by title:", "sort by author:", "sort by value:"};

    puts("Please enter the book title.");
    puts("Enter empty line to quit.");

    while (ct < MAXBKS && s_gets(library[ct].title, LEN) && library[ct].title[0] != 0) {
        puts("Now enter the author.");
        s_gets(library[ct].author, LEN);

        puts("Now enter the value.");
        scanf("%f", &library[ct].value);

        while (getchar() != '\n')
            continue;

        bkpt[ct] = &library[ct];

        if (++ct < MAXBKS)
            puts("Enter the next title.\n");
    }

    if (ct > 0) {
        for (type=0; type<TYPELEN; ++type) {
            puts(stis[type]);
            bsort(bkpt, ct, scbs[type]);

            for (index = 0; index < ct; ++index)
               printf("\t%s by %s value: %.1f\n", bkpt[index]->title, bkpt[index]->author, bkpt[index]->value);

            puts("------------------------------------");
        }
    }


}

void bsort(Book ** sort, int n , SORT_CB_PT call)
{
    int i, j;

    for (i=0; i<n-1; ++i)
        for (j = i+1; j<n; ++j)
            if ((*call)(sort[i],sort[j]) > 0)
                SWAP(Book *, sort[i], sort[j]);

}

int comp_by_title(const Book * first, const Book * second)
{
    return strcmp(first->title, second->title);
}

int comp_by_value(const Book * first, const Book * second)
{
    return first->value - second->value;
}

int comp_by_author(const Book * fir, const Book * sec)
{
    return strcmp(fir->author, sec->author);
}

char * s_gets(char * str, int n)
{
    char * ret_val;
    char * find;

    if ((ret_val = fgets(str, n, stdin))) {
        find = strchr(str, '\n');
        if (find)
            *find = 0;
        else
            while (getchar() != '\n')
                ;
    }

    return ret_val;
}
